/**
 * @Copyright 2012, Founder Mobile Media Technology（Chongqing） Co., Ltd L.P. All
 *            rights reserved. The information contained herein is confidential
 *            and proprietary to Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd, and considered a trade secret as defined under civil and
 *            criminal statutes. Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd shall pursue its civil and criminal remedies in the event of
 *            unauthorized use or misappropriation of its trade secrets. Use of
 *            this information by anyone other than authorized employees of
 *            Founder Mobile Media Technology（Chongqing） Co., Ltd is granted
 *            only under a written non-disclosure agreement, expressly
 *            prescribing the scope and manner of such use.
 */
package com.g2room.http;

/**
 * 
 *
 * @createTime: May 15, 2013 2:58:06 PM
 * @author: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @version: 0.1
 * @lastVersion: 0.1
 * @updateTime: 
 * @updateAuthor: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @changesSum: 
 * 
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Properties;

public class HttpClient{
    protected Socket socket;
    protected BufferedOutputStream sender; 
    protected BufferedInputStream receiver;
    protected ByteArrayInputStream byteStream;   
  
    protected URL targetUrl;   
  
    private int responseCode = -1; 
    private String responseMessage = "";
    private String serverVersion = "";   
 
    private int responseLength =0;
    
    private Properties headerProp = new Properties();
  
    public HttpClient(){}
  
    public HttpClient(String url){
        GET(url);
    }   
  
  
    /* GET方法根据URL，会请求文件、数据库查询结果、程序运行结果等多种内容 */  
  
    public void GET(String url){   
      try{ 
            checkHTTP(url);
            openServer(targetUrl.getHost(),targetUrl.getPort());
            String cmd = "GET " + getURLFormat(targetUrl) + " HTTP/1.0\r\n" 
                                             + getBaseHeads() + "\r\n";
            sendMessage(cmd);  
            receiveMessage(); 
        }
        catch(ProtocolException p){
            p.printStackTrace();
            return;
        }
        catch(UnknownHostException e){
            e.printStackTrace();
            return; 
        } 
        catch(IOException i){
            i.printStackTrace();
            return;
        } 
    }   
  
  
    /* 
     * HEAD方法只请求URL的元信息，不包括URL本身。若怀疑本机和服务器上的 
     * 文件相同，用这个方法检查最快捷有效。 
     */
    public void HEAD(String url){
        try{ 
            checkHTTP(url);
            openServer(targetUrl.getHost(),targetUrl.getPort());
            String cmd = "HEAD " + getURLFormat(targetUrl) + " HTTP/1.0\r\n"  
                                             + getBaseHeads() + "\r\n"; 
            sendMessage(cmd);
            receiveMessage();
        }  
        catch(ProtocolException p){
            p.printStackTrace();
            return; 
        }
        catch(UnknownHostException e){
            e.printStackTrace();
            return;
        }
        catch(IOException i){ 
            i.printStackTrace(); 
            return; 
        } 
    } 
    
    /* 
     * POST方法是向服务器传送数据，以便服务器做出相应的处理。例如网页上常用的 
     * 提交表格。
     */ 
    public void POST(String url, String content){ 
        try{
            checkHTTP(url);
            openServer(targetUrl.getHost(),targetUrl.getPort()); 
//          String cmd = "POST /urls?site=www.1nsh.com&token=cyyQwvwV51mHQGQz HTTP/1.1\r\n"  
//          + getBaseHeads();
          String cmd = "POST /urls?site=www.1nsh.com&token=cyyQwvwV51mHQGQz HTTP/1.1\r\n";
            cmd += "User-Agent: curl/7.12.1\r\n";
            cmd += "Host: data.zz.baidu.com\r\n";
            cmd += "Content-Type: text/plain\r\n";
            cmd += "Content-Length:  (content.length()+2)\r\n";
//            cmd += "1111\r\n";
//            cmd += "1111\r\n";
//            cmd += "Content-type: text/plain;charset='utf-8'\r\n";
//            cmd += "Host:"+ targetUrl.getHost()+":"+targetUrl.getPort()+"\r\n";
//            cmd += "Content-length: " + (content.length()+2) + "\r\n"; 
            cmd += content + "\r\n";
            sendMessage(cmd);
           receiveMessage(); 
          
        }
        catch(ProtocolException p){ 
            p.printStackTrace(); 
            return ; 
        }
        catch(UnknownHostException e){
            e.printStackTrace();
            return ;
        }
        catch(IOException i){ 
            i.printStackTrace();
            return ;
        }
    }
  
    protected void checkHTTP(String url) throws ProtocolException{ 
        try{
            URL targetUrl = new URL(url);
            if(targetUrl == null || 
                    !targetUrl.getProtocol().toUpperCase().equals("HTTP")){ 
                throw new ProtocolException("这不是HTTP协议"); 
            } 
            this.targetUrl = targetUrl;
        }catch(MalformedURLException m){ 
            throw new ProtocolException("协议格式错误");
        }
    }   
  
  
    /*
     * 与Web服务器连接。若找不到Web服务器，InetAddress会引发UnknownHostException 
     * 异常。若Socket连接失败，会引发IOException异常。
     */
    protected void openServer(String host,int port) throws UnknownHostException,IOException{ 
        headerProp.clear(); 
        responseMessage = "";
        responseCode = -1;
  
        if(socket != null){
            closeServer();
        }   
  
        if(byteStream != null){
            byteStream.close();
            byteStream = null; 
        }
  
        InetAddress address = InetAddress.getByName(host);
        socket = new Socket(address,port == -1 ? 80 : port);
     //   socket.setSoTimeout(50000); 
        sender = new BufferedOutputStream(socket.getOutputStream());
        receiver = new BufferedInputStream(socket.getInputStream());
    }
    
    /* 关闭与Web服务器的连接 */
    protected void closeServer() throws IOException{
        if(socket == null){
            return; 
        }
        try{
            socket.close(); 
            sender.close(); 
            receiver.close();
        }catch(IOException i){
            throw i; 
        }
        socket = null;
        sender = null; 
        receiver = null;
    }  
    
    protected String getURLFormat(URL targetUrl){
        String spec = "http://" + targetUrl.getHost();
        if(targetUrl.getPort() != -1){ 
            spec += ":" + targetUrl.getPort(); 
        } 
        
        return spec += targetUrl.getFile(); 
    }
  
    /* 向Web服务器传送数据 */
    protected void sendMessage(String data) throws IOException{
        sender.write(data.getBytes(),0,data.length());
        sender.flush(); 
    } 
  
    /* 接收来自Web服务器的数据 */
    protected void receiveMessage() throws IOException{
        byte data[] = new byte[1024]; 
        int count = 0;
        int word = -1;   
  
        // 解析第一行
        while( (word = receiver.read()) != -1){
            if(word == '\r' || word == '\n'){
                word = receiver.read();
                if(word == '\n') {
                    word = receiver.read();
                }
                break;
            }
            if(count == data.length) {
                data = addCapacity(data);
            }
            data[count++] = (byte) word;
        }   
  
        String message = new String(data,0,count,"utf-8"); 
        System.out.println("message===" + message);
        int mark = message.indexOf(32); 
        serverVersion= message.substring(0,mark);
        while(mark < message.length() && message.charAt(mark + 1) == 32) {
            mark++; 
        }   
        responseCode = Integer.parseInt(message.substring(mark + 1,mark += 4)); 
        responseMessage = message.substring(mark,message.length()).trim(); 
        // 应答状态码和处理请读者添加 
        switch(responseCode){
            case 400: 
                throw new IOException("错误请求"); 
            case 404: 
                throw new FileNotFoundException(getURLFormat(targetUrl));
            case 503:
                throw new IOException("服务器不可用"); 
        }   
  
        if(word == -1){ 
            throw new ProtocolException("信息接收异常终止");
        }   
  
        int symbol = -1;
        count = 0;   
  
        // 解析元信息
        while(word != '\r' && word != '\n' && word > -1){
            if(word == '\t') {
                word = 32;
            }   
  
            if(count == data.length) { 
                data = addCapacity(data);
            }   
  
            data[count++] = (byte) word; 
            parseLine:{
                while( (symbol = receiver.read()) > -1){ 
                    switch(symbol){
                        case '\t':
                            symbol = 32;
                            break;
                        case '\r': 
                        case '\n':
                            word = receiver.read(); 
                            if(symbol == '\r' && word == '\n'){
                                word = receiver.read();
                                if(word == '\r') { 
                                    word = receiver.read();
                                } 
                            }   
  
                            if(word == '\r' || word == '\n' || word > 32){
                                break parseLine; 
                            }
                            symbol = 32; 
                            break;
                    }   
  
                    if(count == data.length) {
                        data = addCapacity(data);
                    }   
  
                    data[count++] = (byte) symbol; 
                }   
  
                word = -1; 
            }   
  
            message = new String(data,0,count);
            mark = message.indexOf(':');
            System.out.println("message===" + message);
            String key = null; 
            if(mark > 0) { 
                key = message.substring(0,mark);
            } 
            mark++;   
  
            while(mark < message.length() && message.charAt(mark) <= 32) {
                mark++;
            }   
  
            String value = message.substring(mark,message.length());
            headerProp.put(key,value);
            count = 0; 
        }   
  
        // 获得正文数据   
  
        while( (word = receiver.read()) != -1){
            if(count == data.length) {
                data = addCapacity(data);
            } 
            data[count++] = (byte) word; 
        }   
  
        if(count > 0) { 
            byteStream = new ByteArrayInputStream(data,0,count);
        }
        // 正文长度
        setResponseLength(count);        
        
        data = null;
        closeServer();
    }   
  
  
    public String getResponseMessage(){
        return responseMessage;
    }
    public int getResponseCode(){
        return responseCode; 
    }
    public String getServerVersion(){ 
        return serverVersion;
    } 
    public InputStream getInputStream(){
        return byteStream; 
    } 
    public synchronized String getHeaderKey(int i){
        if(i >= headerProp.size()){ 
            return null;
        }   
  
        Enumeration<?> enumss = headerProp.propertyNames();
        String key = null;
        for(int j = 0; j <= i; j++){
            key = (String) enumss.nextElement();
        } 
  
        return key;
    }   
  
  
    public synchronized String getHeaderValue(int i){
        if(i >= headerProp.size()){
            return null;
        }   
  
        return headerProp.getProperty(getHeaderKey(i)); 
    }   
  
  
    public synchronized String getHeaderValue(String key){
        return headerProp.getProperty(key); 
    }   
  
  
    protected String getBaseHeads(){
        String inf = "User-Agent: ZealHttp/1.0\r\nAccept: www/source; text/html; image/gif; */*\r\n";
        return inf;
    }   
  
  
    private byte[] addCapacity(byte rece[]){
        byte temp[] = new byte[rece.length + 1024];
        System.arraycopy(rece,0,temp,0,rece.length);
        return temp; 
    }

	public int getResponseLength() {
		return responseLength;
	}

	public void setResponseLength(int responseLength) {
		this.responseLength = responseLength;
	}
	
	public static void main(String[] str) {
		/**
		 POST /urls?site=www.1nsh.com&token=cyyQwvwV51mHQGQz HTTP/1.1
User-Agent: curl/7.12.1 
Host: data.zz.baidu.com 
Content-Type: text/plain 
Content-Length: 83 
http://www.example.com/1.html
http://www.example.com/2.html
		 */
		
		String content = "http://www.1nsh.com/index .html\r\nhttp://www.1nsh.com/feel/d17114.html\r\n";
		HttpClient httpClient = new HttpClient();
		httpClient.POST("http://data.zz.baidu.com/urls?site=www.1nsh.com&token=cyyQwvwV51mHQGQz",content);
	}
  
}  
